﻿using Baidu.Api.Request;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Baidu.Api.Util
{
    public static class BaiduUtils
    {

        #region cloud match

        public const int SLICE_SIZE = 256 * 1024;

        public static string GetMD5(byte[] buffer)
        {
            MD5 md5 = MD5.Create();
            buffer = md5.ComputeHash(buffer);
            return GetString(buffer);
        }

        public static string GetMD5(Stream stream)
        {
            MD5 md5 = MD5.Create();
            stream.Position = 0;
            var buffer = md5.ComputeHash(stream);
            return GetString(buffer);
        }

        public static string GetSliceMD5(byte[] buffer)
        {
            var array = new byte[SLICE_SIZE];
            Array.Copy(buffer, array, SLICE_SIZE);
            return GetMD5(array);
        }

        public static string GetSliceMD5(Stream stream)
        {
            var array = new byte[SLICE_SIZE];
            stream.Position = 0;
            if (array.Length == stream.Read(array, 0, array.Length))
            {
                return GetMD5(array);
            }
            return null;
        }

        public static string GetCrc32(Stream stream)
        {
            stream.Position = 0;
            var buffer = Crc32.ComputeChecksumBytes(GetBytes(stream));
            return GetString(buffer);
        }

        public static string GetCrc32(byte[] buffer)
        {
            buffer = Crc32.ComputeChecksumBytes(buffer);
            return GetString(buffer);
        }

        public static IEnumerable<byte> GetBytes(Stream stream)
        {
            int read;
            int bufferSize = 1048576;
            byte[] buffer = new byte[bufferSize];
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                for (int i = 0; i < read; i++)
                {
                    yield return buffer[i];
                }
            }
        }

        public static string GetString(IEnumerable<byte> buffer)
        {
            StringBuilder result = new StringBuilder();
            foreach (var b in buffer)
            {
                string hex = b.ToString("x");
                if (hex.Length == 1)
                {
                    result.Append("0");
                }
                result.Append(hex);
            }
            return result.ToString();
        }

        //public static FileRapidUploadRequest CreateCloudMatch(Stream stream)
        //{
        //    var req = new FileRapidUploadRequest();
        //    req.ContentLength = (uint)stream.Length;

        //    uint crc = 0xffffffff;
        //    int read = 0;
        //    int bufferSize = 1048576;
        //    byte[] buffer = new byte[bufferSize];
        //    MD5 md5 = MD5.Create();

        //    int len = (int)Math.Ceiling((double)stream.Length / bufferSize);

        //    for (int i = 0; i < len; i++)
        //    {
        //        read = stream.Read(buffer, 0, buffer.Length);

        //        if (i == 0)
        //        {
        //            req.SliceMD5 = GetSliceMD5(buffer);
        //        }
        //        crc = Crc32.ComputeChecksum(buffer, crc);
        //    }

        //    req.ContentCrc32 = GetString(BitConverter.GetBytes(crc));
        //    return req;
        //}

        #endregion

        public static IDictionary<string, string> SplitUrlQuery(string query)
        {
            IDictionary<string, string> result = new Dictionary<string, string>();

            string[] pairs = query.Split(new char[] { '&' });
            if (pairs != null && pairs.Length > 0)
            {
                foreach (string pair in pairs)
                {
                    string[] oneParam = pair.Split(new char[] { '=' }, 2);
                    if (oneParam != null && oneParam.Length == 2)
                    {
                        result.Add(oneParam[0], oneParam[1]);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 清除字典中值为空的项。
        /// </summary>
        /// <param name="dict">待清除的字典</param>
        /// <returns>清除后的字典</returns>
        public static IDictionary<string, T> CleanupDictionary<T>(IDictionary<string, T> dict)
        {
            IDictionary<string, T> newDict = new Dictionary<string, T>(dict.Count);
            IEnumerator<KeyValuePair<string, T>> dem = dict.GetEnumerator();

            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                T value = dem.Current.Value;
                if (value != null)
                {
                    newDict.Add(name, value);
                }
            }

            return newDict;
        }

        ///// <summary>
        ///// 把JSON解释为字典结构。
        ///// </summary>
        ///// <param name="json">JSON字符串</param>
        ///// <returns>字典</returns>
        //public static IDictionary ParseJson(string json)
        //{
        //    return JsonConvert.Import(json) as IDictionary;
        //}

        /// <summary>
        /// 把JSON解释为API响应对象。
        /// </summary>
        /// <typeparam name="T">API响应类型</typeparam>
        /// <param name="json">JSON字符串</param>
        /// <returns>API响应对象</returns>
        public static T ParseResponse<T>(string json) where T : BaiduResponse
        {
            return (T)JsonConvert.DeserializeObject(json, typeof(T));
        }

        /// <summary>
        /// 获取从1970年1月1日到现在的毫秒总数。
        /// </summary>
        /// <returns>毫秒数</returns>
        public static long GetCurrentTimeMillis(DateTime time)
        {
            return (long)time.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
        }

        public static string CreateErrorJson(int errCode, string errMsg)
        {
            var errObj = new Dictionary<string, object>();
            errObj.Add("request_id", 0);
            errObj.Add("error_code", errCode);
            errObj.Add("error_msg", errMsg);
            return JsonConvert.SerializeObject(errObj);
        }
    }
}
